import java.util.ArrayList;
import java.util.Random;

import javax.sound.midi.MetaEventListener;
import javax.sound.midi.MetaMessage;
import javax.sound.midi.MidiEvent;
import javax.sound.midi.MidiSystem;
import javax.sound.midi.Sequence;
import javax.sound.midi.Sequencer;
import javax.sound.midi.ShortMessage;
import javax.sound.midi.Track;


public class HeartModel implements HeartModelInterface, Runnable{
	
	ArrayList  beatObservers = new ArrayList();
	ArrayList  bpmObservers = new ArrayList();
	int time = 1000;
	int bpm = 90;
	Random random = new Random( System.currentTimeMillis());
	Thread thread;
	
	HeartModel(){
		thread = new Thread(this);
		thread.start();
	}
	
	public void run()
	{
		int lastrate = -1;
		for(;;)
		{
			int change = random.nextInt(10);
			if( random.nextInt(2) == 0){
				change = 0 - change;
			}
			int rate = 60000/(time + change);
			if( rate < 120 && rate > 50 ){
				time += change;
			}
			notifyBeatObservers();
			if( rate != lastrate ){
				lastrate = rate;
				notifyBPMObservers();
			}
			try{
				thread.sleep(time);
			} catch (Exception e){
				
			}
		}
		
		
	}
	
	public int getHeartRate(){
		return 60000/time;
	}

	public void registerObserver(BeatObserver o){
		beatObservers.add(o);
	}

	private void notifyBeatObservers() {
		// TODO Auto-generated method stub
		for( int i=0; i < beatObservers.size(); i++ ){
			BeatObserver observer = (BeatObserver) beatObservers.get(i);
			observer.updateBeat();
		}
		
	}
	
	private void notifyBPMObservers() {
		// TODO Auto-generated method stub
		for( int i=0; i < bpmObservers.size(); i++ ){
			BPMObserver observer = (BPMObserver) bpmObservers.get(i);
			observer.updateBPM();
		}
		
	}
	
	public void registerObserver(BPMObserver o ){
		bpmObservers.add(o);
	}
	
	public void removeObserver(BeatObserver o){
		int i= beatObservers.indexOf(o);
		if( i >= 0 ) {
			beatObservers.remove(i);
		}
	}

	public int getBPM() {
		// TODO Auto-generated method stub
		return this.bpm;
	}


     public void removeObserver(BPMObserver o) {
		// TODO Auto-generated method stub
		int i= bpmObservers.indexOf(o);
		if( i >= 0 ) {
			bpmObservers.remove(i);
		}
		
	}

}
